(转载)基于Unity~UGUI的简单UI框架(附UIFramework源码)

您所在的位置:网站首页 gameframework框架 ui (转载)基于Unity~UGUI的简单UI框架(附UIFramework源码)

(转载)基于Unity~UGUI的简单UI框架(附UIFramework源码)

2024-05-17 18:34| 来源: 网络整理| 查看: 265

此博客跟随siki老师的课程笔记生成,感谢siki老师的辛勤付出! 此框架功能较简单,适用于学习,可以很好的锻炼我们的设计思想 框架源码地址: UIFramework litjson.dll下载地址: litjson

不使用UI框架存在的一些问题

1.随着游戏系统的复杂,UI控件越来越多,各个UI直接的通讯,以及UI与GameObject之间的通讯形成一张复杂的蜘蛛网, 拖着拖着,有时候我都忘了哪个对象跟哪个对象关联了。如果是别人要看我的程序,我估计他找半天都找不到UI逻辑的入口。 2.耦合性非常严重,如果要改变需求,更改某个UI或者更改某个游戏对象,那么你需要再手动全部与该对象关联的物件重新更改一次。 3.作为强迫症的程序员,最受不了程序代码的混乱。这种组织方式十分“不优雅”,看着很乱。 鉴于以上各种情况,我们需要寻找一种新的,科学的,高效的UI管理方式

UI框架总揽:

这里写图片描述

创建测试面板(非框架部分)

将面板以Prefab形式放入Resources文件夹下面,便于框架加载面板 UIPanel

创建json文件和UIPanelType类来保存所有的面板信息

UIPanelType.json:

{ "panelInfoList": [ {"panelType":"MainMenu","path":"UIPanel/MainMenuPanel"}, {"panelType":"ItemMessage","path":"UIPanel/ItemMessagePanel"}, {"panelType":"Knapsack","path":"UIPanel/KnapsackPanel"}, {"panelType":"Shop","path":"UIPanel/ShopPanel"}, {"panelType":"Skill","path":"UIPanel/SkillPanel"}, {"panelType":"System","path":"UIPanel/SystemPanel"}, {"panelType":"Task","path":"UIPanel/TaskPanel"} ] }

UIPanelType.cs:

public class UIPanelType { public const string MainMenu = "MainMenu"; public const string Knapsack = "Knapsack"; public const string ItemMessage = "ItemMessage"; public const string Shop = "Shop"; public const string Skill = "Skill"; public const string System = "System"; public const string Task = "Task"; } 开发UIManger来解析面板信息json文件(框架核心:UIManager)

UIManager为框架的核心,全局只有一个UIManager,因此UIManager要使用单例模式 现阶段的完整的UIManager.cs(后续还会继续完善):

using System.Collections.Generic; using System.Collections; using System; using UnityEngine; using LitJson; public class UIPanelManager { private static UIPanelManager _instance; public static UIPanelManager Instance { get { if (_instance == null) { _instance = new UIPanelManager(); } return _instance; } } private Dictionary panelPathDict; //private Dictionary //private Stack private UIPanelManager() { ParseUIPanelTypeJson(); } private void ParseUIPanelTypeJson() { panelPathDict = new Dictionary(); TextAsset textUIPanelType = Resources.Load("UIPanelTypeJson"); UIPanelInfoList panelInfoList = JsonMapper.ToObject(textUIPanelType.text); foreach (UIPanelInfo panelInfo in panelInfoList.panelInfoList) { panelPathDict.Add(panelInfo.panelType, panelInfo.path); Debug.Log(panelInfo.panelType + ":" + panelInfo.path); } } } 开发BasePanel抽象类(各个UIPanel的基类)

BasePanel给每个Panel定义了四个事件: OnEnter:面板进入时调用 OnPause:面板停止时调用(鼠标与面板的交互停止) OnResume:面板恢复使用时调用(鼠标与面板的交互恢复) OnExit:面板退出时调用

using UnityEngine; public abstract class BasePanel : MonoBehaviour { public abstract void OnEnter(); public abstract void OnPause(); public abstract void OnResume(); public abstract void OnExit(); }

给各个面板添加UIPanel类(非框架部分) 这里写图片描述

using UnityEngine; public class MainMenuPanel : BasePanel { public override void OnEnter() { } public override void OnPause() { } public override void OnResume() { } public override void OnExit() { } } 对UI面板Prefab实例化的创建与管理

获取Panel(如果panel没有被实例化,进行实例化,并且存储到已经实例化好的panel字典中)

private BasePanel GetPanel(string panelType) { BasePanel panel = panelDict.GetValue(panelType); //如果没有实例化面板,寻找路径进行实例化,并且存储到已经实例化好的字典面板中 if (panel == null) { string path = panelPathDict.GetValue(panelType); Transform panelTransform = GameObject.Instantiate(Resources.Load(path), canvasTransform).transform; panel = panelTransform.GetComponent(); panelDict.Add(panelType, panel); } return panel; }

字典的扩展:

using System.Collections.Generic; public static class DictTool { public static Tvalue GetValue(this Dictionary dict, Tkey key) { Tvalue value = default(Tvalue); dict.TryGetValue(key, out value); return value; } }

现阶段的完整的UIManager.cs(后续还会继续完善):

using System.Collections.Generic; using System.Collections; using System; using UnityEngine; using LitJson; public class UIPanelManager { private static UIPanelManager _instance; private Transform canvasTransform; private Transform CanvasTransform { get { if (canvasTransform == null) { canvasTransform = GameObject.Find("Canvas").transform; } return canvasTransform; } } public static UIPanelManager Instance { get { if (_instance == null) { _instance = new UIPanelManager(); } return _instance; } } private Dictionary panelPathDict; private Dictionary panelDict; //private Stack private UIPanelManager() { ParseUIPanelTypeJson(); } private BasePanel GetPanel(string panelType) { if (panelDict == null) { panelDict = new Dictionary(); } BasePanel panel = panelDict.GetValue(panelType); //如果没有实例化面板,寻找路径进行实例化,并且存储到已经实例化好的字典面板中 if (panel == null) { string path = panelPathDict.GetValue(panelType); GameObject panelGo = GameObject.Instantiate(Resources.Load(path), CanvasTransform, false); panel = panelGo.GetComponent(); panelDict.Add(panelType, panel); } return panel; } //解析json文件 private void ParseUIPanelTypeJson() { panelPathDict = new Dictionary(); TextAsset textUIPanelType = Resources.Load("UIPanelTypeJson"); UIPanelInfoList panelInfoList = JsonMapper.ToObject(textUIPanelType.text); foreach (UIPanelInfo panelInfo in panelInfoList.panelInfoList) { panelPathDict.Add(panelInfo.panelType, panelInfo.path); //Debug.Log(panelInfo.panelType + ":" + panelInfo.path); } } } 开发界面存储栈,并进行出栈和入栈操作

【设计理念】 1.鼠标只允许和一个界面进行交互,当一个界面显示后,上一个界面要停止和鼠标的交互 2.界面显示,进行入栈操作(Push,OnEnter),停止上一个界面(OnPause) 3.界面隐藏,进行出栈操作(Pop,OnExit),恢复上一个界面(OnResume)

private Stack panelStack; public void PushPanel(string panelType) { if (panelStack == null) { panelStack = new Stack(); } //停止上一个界面 if (panelStack.Count > 0) { BasePanel topPanel = panelStack.Peek(); topPanel.OnPause(); } BasePanel panel = GetPanel(panelType); panelStack.Push(panel); panel.OnEnter(); } public void PopPanel() { if (panelStack == null) { panelStack = new Stack(); } if (panelStack.Count 0) { BasePanel panel = panelStack.Peek(); panel.OnResume(); } } 控制Panel之间的跳转(非框架部分)

完善面板中的一些操作,实现面板之间的跳转,此部分不是框架部分,省略! MainMenuPanel.cs:

using UnityEngine; using UnityEngine.UI; public class MainMenuPanel : BasePanel { private Button TaskButton; private Button KnapsackButton; private Button SkillButton; private Button ShopButton; private Button SystemButton; private CanvasGroup canvasGroup; void Awake() { TaskButton = transform.Find("IconPanel/TaskButton").GetComponent(); KnapsackButton = transform.Find("IconPanel/KnapsackButton").GetComponent(); SkillButton = transform.Find("IconPanel/SkillButton").GetComponent(); ShopButton = transform.Find("IconPanel/ShopButton").GetComponent(); SystemButton = transform.Find("IconPanel/SystemButton").GetComponent(); canvasGroup = transform.GetComponent(); TaskButton.onClick.AddListener(OnTaskButtonClick); KnapsackButton.onClick.AddListener(OnKnapsackButtonClick); SkillButton.onClick.AddListener(OnSkillButtonClick); ShopButton.onClick.AddListener(OnShopButtonClick); SystemButton.onClick.AddListener(OnSystemButtonClick); } void OnDestory() { TaskButton.onClick.RemoveListener(OnTaskButtonClick); KnapsackButton.onClick.RemoveListener(OnKnapsackButtonClick); SkillButton.onClick.RemoveListener(OnSkillButtonClick); ShopButton.onClick.RemoveListener(OnShopButtonClick); SystemButton.onClick.RemoveListener(OnSystemButtonClick); } public override void OnEnter() { } public override void OnPause() { canvasGroup.blocksRaycasts = false; } public override void OnResume() { canvasGroup.blocksRaycasts = true; } public override void OnExit() { } private void OnTaskButtonClick() { UIPanelManager.Instance.PushPanel(UIPanelType.Task); } private void OnKnapsackButtonClick() { UIPanelManager.Instance.PushPanel(UIPanelType.Knapsack); } private void OnSkillButtonClick() { UIPanelManager.Instance.PushPanel(UIPanelType.Skill); } private void OnShopButtonClick() { UIPanelManager.Instance.PushPanel(UIPanelType.Shop); } private void OnSystemButtonClick() { UIPanelManager.Instance.PushPanel(UIPanelType.System); } } UI框架(完结)

UI框架 【BasePanel(基类):所有面板继承自BasePanel】 定义了四个事件: OnEnter:面板进入时调用 OnPause:面板停止时调用(鼠标与面板的交互停止) OnResume:面板恢复使用时调用(鼠标与面板的交互恢复) OnExit:面板退出时调用

using UnityEngine; public abstract class BasePanel : MonoBehaviour { public abstract void OnEnter(); public abstract void OnPause(); public abstract void OnResume(); public abstract void OnExit(); }

【GameRoot】 实例化游戏中的主面板

using System.Collections; using System.Collections.Generic; using UnityEngine; using System; public class GameRoot : MonoBehaviour { void Start () { UIPanelManager panelManager = UIPanelManager.Instance; panelManager.PushPanel(UIPanelType.MainMenu); } }

【UIPanelManager(框架的核心,单例)】 进行解析面板信息json文件,实例化面板Prefab,面板的入栈和出栈等等一系列操作

using System.Collections.Generic; using System.Collections; using System; using UnityEngine; using LitJson; public class UIPanelManager { private static UIPanelManager _instance; private Transform canvasTransform; private Transform CanvasTransform { get { if (canvasTransform == null) { canvasTransform = GameObject.Find("Canvas").transform; } return canvasTransform; } } public static UIPanelManager Instance { get { if (_instance == null) { _instance = new UIPanelManager(); } return _instance; } } private Dictionary panelPathDict; private Dictionary panelDict; private Stack panelStack; private UIPanelManager() { ParseUIPanelTypeJson(); } public void PushPanel(string panelType) { if (panelStack == null) { panelStack = new Stack(); } //停止上一个界面 if (panelStack.Count > 0) { BasePanel topPanel = panelStack.Peek(); topPanel.OnPause(); } BasePanel panel = GetPanel(panelType); panelStack.Push(panel); panel.OnEnter(); } public void PopPanel() { if (panelStack == null) { panelStack = new Stack(); } if (panelStack.Count 0) { BasePanel panel = panelStack.Peek(); panel.OnResume(); } } private BasePanel GetPanel(string panelType) { if (panelDict == null) { panelDict = new Dictionary(); } BasePanel panel = panelDict.GetValue(panelType); //如果没有实例化面板,寻找路径进行实例化,并且存储到已经实例化好的字典面板中 if (panel == null) { string path = panelPathDict.GetValue(panelType); GameObject panelGo = GameObject.Instantiate(Resources.Load(path), CanvasTransform, false); panel = panelGo.GetComponent(); panelDict.Add(panelType, panel); } return panel; } //解析json文件 private void ParseUIPanelTypeJson() { panelPathDict = new Dictionary(); TextAsset textUIPanelType = Resources.Load("UIPanelTypeJson"); UIPanelInfoList panelInfoList = JsonMapper.ToObject(textUIPanelType.text); foreach (UIPanelInfo panelInfo in panelInfoList.panelInfoList) { panelPathDict.Add(panelInfo.panelType, panelInfo.path); //Debug.Log(panelInfo.panelType + ":" + panelInfo.path); } } }

【litjson】 json文件解析的工具

【UIPanelTypeJson(保存面板信息的json文件)】 1.此文件需要加载,保存到Resources文件下 2.保存了面板的类型(相当于名称)和面板Prefab的路径(实例化面板时要用到) 3.每添加一个面板,都要在此文件添加该面板对应的信息

{ "panelInfoList": [ {"panelType":"MainMenu","path":"UIPanel/MainMenuPanel"}, {"panelType":"ItemMessage","path":"UIPanel/ItemMessagePanel"}, {"panelType":"Knapsack","path":"UIPanel/KnapsackPanel"}, {"panelType":"Shop","path":"UIPanel/ShopPanel"}, {"panelType":"Skill","path":"UIPanel/SkillPanel"}, {"panelType":"System","path":"UIPanel/SystemPanel"}, {"panelType":"Task","path":"UIPanel/TaskPanel"} ] }

【DictTool】 Dictionnary的拓展工具类

using System.Collections.Generic; public static class DictTool { public static Tvalue GetValue(this Dictionary dict, Tkey key) { Tvalue value = default(Tvalue); dict.TryGetValue(key, out value); return value; } }

【UIPanelInfo(面板的信息类)】 包括面板的名称和面板Prefab的路径 用于和json文件进行映射

using System; [Serializable] public class UIPanelInfo { public string panelType; public string path; public UIPanelInfo() { } }

【UIPanelInfoList(面板信息集合类)】 用于和json文件进行映射

using System; using System.Collections.Generic; [Serializable] public class UIPanelInfoList { public List panelInfoList; public UIPanelInfoList() { } }

【UIPanelType(面板的类型)】 用来记录面板的类型(名称) 每添加一个面板都要在此类里面添加对应面板的类型

public class UIPanelType { public const string MainMenu = "MainMenu"; public const string Knapsack = "Knapsack"; public const string ItemMessage = "ItemMessage"; public const string Shop = "Shop"; public const string Skill = "Skill"; public const string System = "System"; public const string Task = "Task"; }

(完)

 

--------------------- 作者:cchoop来源:CSDN原文:https://blog.csdn.net/qq_34937637/article/details/80374387



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3